///////////////////////////////////////////////////////////////////////////////
// Includes
#include <Windows.h>
#include <guiGraphicsDisplayEmulator.h>
#include <guiColorGraphicsDriver.h>
#include <guiColors.h>
#include "drvIOConfig.h"

///////////////////////////////////////////////////////////////////////////////
// Module global variables
static BITMAPINFO  l_bitmapinfo;
static LPBYTE      l_bitmapbits;        // Pointer to the (device independent) bitmap data
static int         l_bitmaplinesize;    // Size in bytes of a bitmap scanline
static int         l_bitmapwidth;       // Width of bitmap in pixels
static int         l_bitmapheight;      // Height of bitmap in pixels
static HANDLE      l_hbm;               // Bitmap handle
static HDC         l_hdc;								// Device context handle
static dosColor		 l_background_color;
static dosColor		 l_foreground_color;
static dosWord		 l_data_window_left;
static dosWord		 l_data_window_top;
static dosWord     l_data_window_right;
static dosWord		 l_data_window_bottom;


///////////////////////////////////////////////////////////////////////////////
// Local function prototypes

///////////////////////////////////////////////////////////////////////////////
// Initialize color graphics system
void guiInitColorGraphicsDriver(void)
{
    LPVOID  pb;

		guiInitDisplayEmulatorDriver();

		// Create memory device context
    l_hdc = CreateCompatibleDC( 0 );

    // Create DIB section to hold bitmap data
    ZeroMemory( &l_bitmapinfo, sizeof(l_bitmapinfo) );
    l_bitmapinfo.bmiHeader.biSize = sizeof(l_bitmapinfo.bmiHeader);
    l_bitmapinfo.bmiHeader.biWidth = guiSCREEN_WIDTH;
    l_bitmapinfo.bmiHeader.biHeight = -guiSCREEN_HEIGHT; // Create top-down bitmap
    l_bitmapinfo.bmiHeader.biPlanes = 1;
    l_bitmapinfo.bmiHeader.biBitCount = 24;
    l_bitmapinfo.bmiHeader.biCompression = BI_RGB;
    l_bitmapinfo.bmiHeader.biSizeImage = 0;
    l_bitmapinfo.bmiHeader.biXPelsPerMeter = 1;
    l_bitmapinfo.bmiHeader.biYPelsPerMeter = 1;
    l_bitmapinfo.bmiHeader.biClrUsed = 0;
    l_bitmapinfo.bmiHeader.biClrImportant = 0;

    l_hbm = CreateDIBSection( l_hdc,
      &l_bitmapinfo,
      DIB_RGB_COLORS,
      &pb,
      0,
      0 );

    // Associate the bitmap to the device context
    SelectObject( l_hdc, l_hbm );

    l_bitmapbits = (LPBYTE)pb;
    l_bitmaplinesize = 4 * ((guiSCREEN_WIDTH*3 + 3) / 4); // Length of a scan line 
    l_bitmapwidth = guiSCREEN_WIDTH;
    l_bitmapheight = guiSCREEN_HEIGHT;
}

void guiDIBDriverCleanUp(void)
{
    DeleteDC( l_hdc );
    DeleteObject( l_hbm );
}

void guiClearScreen(void)
{
	ZeroMemory( l_bitmapbits, l_bitmaplinesize*l_bitmapheight );
}

void guiRefreshScreen(HDC in_hdc)
{
	StretchDIBits(  in_hdc,
  0, 0,
  guiSCREEN_WIDTH*guiemu_ZOOM, guiSCREEN_HEIGHT*guiemu_ZOOM,
  0, 0,
  guiSCREEN_WIDTH, guiSCREEN_HEIGHT,
	l_bitmapbits,
	&l_bitmapinfo,
  DIB_RGB_COLORS,
  SRCCOPY );
}

void guiSetForegroundColor(dosColor in_color)
{
	l_foreground_color = in_color;
}

void guiSetBackgroundColor(dosColor in_color)
{
	l_background_color = in_color;
}


dosColor guiGetPixelColor(dosWord in_x, dosWord in_y)
{
	LPBYTE  pb;
 
	if( in_x < 0 || in_x >= l_bitmapwidth || in_y < 0 || in_y >= l_bitmapheight )
		return 0;

	pb = l_bitmapbits + in_y * l_bitmaplinesize + in_x * 3;
	
	return pb[0] | ((DWORD)pb[1] << 8) | ((DWORD)pb[2] << 16);
}

void guiSetForegroundPixel(dosWord in_x, dosWord in_y)
{
	LPBYTE  pb;
	
	if( in_x < 0 || in_x >= l_bitmapwidth || in_y < 0 || in_y >= l_bitmapheight )
		return;

	pb = l_bitmapbits + in_y * l_bitmaplinesize + in_x * 3;
	*pb++ = (BYTE)(l_foreground_color );			// R
	*pb++ = (BYTE)(l_foreground_color >> 8);	// G
	*pb   = (BYTE)(l_foreground_color >> 16);	// B
}

void guiSetBackgroundPixel(dosWord in_x, dosWord in_y)
{
	LPBYTE  pb;
	
	if( l_background_color == COLOR_TRANSPARENT || in_x < 0 || in_x >= l_bitmapwidth || in_y < 0 || in_y >= l_bitmapheight )
		return;

	pb = l_bitmapbits + in_y * l_bitmaplinesize + in_x * 3;
	*pb++ = (BYTE)(l_background_color );			// R
	*pb++ = (BYTE)(l_background_color >> 8);	// G
	*pb   = (BYTE)(l_background_color >> 16);	// B
}
